home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #5 / Amiga Plus CD - 2000 - No. 5.iso / Tools / Dev / FPSE_src / cpu2.c < prev    next >
C/C++ Source or Header  |  2000-01-01  |  13KB  |  506 lines

  1. /*
  2.     R3000 emu
  3.  
  4.     (C) 1999 BERO
  5. */
  6.  
  7. #include "fpse.h"
  8.  
  9. R3000_REG reg;
  10.  
  11. // int stop;
  12.  
  13. void printpc(void)
  14. {
  15.     PRINTF("%08x:",(int)(PC-4));
  16. }
  17.  
  18. void Exception(int cd)
  19. {
  20. //  if (cd == E_Bp*4) cd = E_Sys*4; // Avoid break exeception
  21.     if (in_slot) {
  22.         EPC=PC-4; CAUSE=cd | 0x80000000;
  23.     } else {
  24.         EPC=PC;
  25.         CAUSE = cd;
  26.     }
  27.     PRINTF("Exception:%x\n",cd);
  28. //  CAUSE = (CAUSE & ~0x3c) | cd;
  29.     SR = (SR & ~0x3f)| ((SR<<2)&0x3f);;
  30.     PC=0x80000080;
  31.     SETPC(PC);
  32.     if (exception_handler()) FPSE_Flags |= STOP;
  33.     SETPC(PC);
  34. }
  35.  
  36. /* hwŠ„‚肱‚Ý */
  37.  
  38. void Interrupt(void)
  39. {
  40. //  PRINTF("Interrupt %x\n",PC);
  41.     if (SR&1) { /* Š„‚荞‚Ý‹–‰Â‚³‚ê‚Ä‚é‚© */
  42.         if (SR & 0x400) { /* Žw’芄‚肱‚Ý‚Í‹–‰Â‚³‚ê‚Ä‚é‚© */
  43.             Exception(0x400);
  44.         }
  45.     }
  46. }
  47.  
  48. void Reset(void)
  49. {
  50.     memset(®,0,sizeof(reg));
  51.     PC = 0xbfc00000;
  52.  /* kernel mode */
  53.     SETPC(PC);
  54. }
  55.  
  56. #ifndef INT64
  57. static void multu(UINT32 v1,UINT32 v2)
  58. {
  59.     UINT32  v1h,v1l,v2h,v2l;
  60.     UINT32  ll,hl,lh,hh,mid,mid2;
  61.  
  62.     v1l = (UINT16)v1;
  63.     v1h = ((UINT32)v1)>>16;
  64.     v2l = (UINT16)v2;
  65.     v2h = ((UINT32)v2)>>16;
  66.  
  67.     ll = v1l*v2l; 
  68.     hl = v1h*v2l;
  69.     lh = v1l*v2h;
  70.     hh = v1h*v2h;
  71. /*
  72.         |ll|ll|
  73.      |lh|lh|
  74.      |hl|hl|
  75.   |hh|hh|
  76. --------------
  77.      | mid |
  78.   |carry|
  79. */
  80.     mid = hl+lh;
  81.     if (mid<hl) hh+=0x10000;
  82.     mid2 = mid + (ll>>16);
  83.     if (mid2<mid) hh+=0x10000;
  84.     rLO = (UINT16)ll|(mid2<<16);
  85.     rHI = hh+(mid>>16);
  86. }
  87.  
  88. static void mult(INT32 v1,INT32 v2)
  89. {
  90.     int sign = (v1^v2)<0;
  91.  
  92.     if (v1<0) {v1 = -v1;}
  93.     if (v2<0) {v2 = -v2;}
  94.     multu(v1,v2);
  95.     if (sign) {
  96.         rLO = -rLO;
  97.         rHI = ~rHI;
  98.         if (rLO==0) rHI++;
  99.     }
  100. }
  101. #endif
  102.  
  103. void bioscheck(int pc)
  104. {
  105.     switch(pc) {
  106.     case 0xc0:
  107.     case 0xb0:
  108.     case 0xa0:
  109.         if (biosprint(pc)) {
  110.             /* ”ñƒTƒ|[ƒg */
  111. //          stop = 1;
  112.         }
  113.         SETPC(PC);
  114.         break;
  115.     }
  116. }
  117.  
  118. #define   JUMP(pc) { UINT32 newpc=(pc);       \
  119.                    FPSE_Flags |= IN_SLOT;   \
  120.                    doInst();                \
  121.                    FPSE_Flags &= ~IN_SLOT;  \
  122.                    PC=newpc; }
  123.  
  124. #define   NOT_IMPREMENT(cd) { printf("not imprement %s: %08x\n",cd,(int)code); \
  125.                             FPSE_Flags |= STOP; }
  126.  
  127. void setpc(int pc)
  128. {
  129.     PC = pc; SETPC(PC);
  130. }
  131.  
  132. #define   INSTSIZE (0x280000/4)
  133. static char flg[INSTSIZE];
  134. static int nopcounter;
  135.  
  136. extern int breakpoint;
  137.  
  138. // #define SUPPORT_HBP
  139.  
  140. #ifdef SUPPORT_HBP
  141. #define CHECK_EXECBREAK(adr) \
  142.     if ((CPR0[7] & 0x01000000)==0x01000000) && (adr & CPR0[11])==CPR0[3] ) {\
  143. /* read break happen */ \
  144.     }
  145.  
  146. #define CHECK_READBREAK(adr) \
  147.     if ((CPR0[7] & 0x06000000)==0x06000000) && (adr & CPR0[9])==CPR0[5] ) {\
  148. /* read break happen */ \
  149.     }
  150.  
  151. #define CHECK_WRITEBREAK(adr) \
  152.     if ((CPR0[7] & 0x0a000000)==0x0a000000) && (adr & CPR0[9])==CPR0[5] ) {\
  153. /* read break happen */ \
  154.     }
  155.  
  156. #else
  157. #define CHECK_EXECBREAK(adr)
  158. #define CHECK_READBREAK(adr)
  159. #define CHECK_WRITEBREAK(adr)
  160. #endif
  161.  
  162. void doInst(void)
  163. {
  164.     UINT32  code;
  165. /*
  166.     if (PC==breakpoint) watch();
  167. */
  168.     if (stop) return;
  169.  
  170.     CHECK_EXECBREAK(PC);
  171.  
  172.     code = FETCH(PC);
  173.  
  174.     if (disasmflg) {
  175.         UINT32 adr=PC;
  176.         static char strbuf[256];
  177.         if (adr>0xbfc00000) adr = adr-0xbfc00000+0x200000;
  178.         else adr&=0x1fffff;
  179.         if (!flg[adr/4] || debug) {
  180.             flg[adr/4]=1;
  181.             disasm(strbuf,code,PC);
  182.             printf("%08x %08x %s\n",(int)PC,(int)code,strbuf);
  183.         }
  184.     }
  185.     PC+=4;
  186. /*
  187.     if (reg.r[0]) {
  188.         PRINTF("reg0 boken\n");
  189.         FPSE_Flags |= STOP;
  190.     }
  191. */
  192.     if (!code) {
  193. /* nop */
  194.         nopcounter++;
  195.         if (nopcounter>100) {
  196.             FPSE_Flags |= STOP;
  197.             printpc();
  198.             PRINTF("too long nop\n");
  199.         }
  200.         return;
  201.     }
  202.     nopcounter = 0;
  203.  
  204.     switch(code>>26) {
  205.     case SPECIAL:
  206.         switch(code&63) {
  207.         case SLL:   rd = (UINT32)rt << ((code>>6)&31); break;
  208.         case SRL:   rd = (UINT32)rt >> ((code>>6)&31); break;
  209.         case SRA:   rd =  (INT32)rt >> ((code>>6)&31); break;
  210.         case SLLV:  rd = (UINT32)rt << (rs&31); break;
  211.         case SRLV:  rd = (UINT32)rt >> (rs&31); break;
  212.         case SRAV:  rd =  (INT32)rt >> (rs&31); break;
  213.  
  214.         case ADD:
  215. #if 1
  216.             rd = rs + rt;
  217. #else
  218.             {
  219.             int tmp = rs + rt;
  220.             /* •„†‚ª“¯‚¶ && ‘O‚ÆŒã‚Ì•„†‚ªˆá‚¤@*/
  221.             if ((INT32)(rs^rt)>=0 && (INT32)(rs^tmp)<0) {
  222.                 EXCEPTION(E_Ovf);
  223.             } else {
  224.                 rd = tmp;
  225.             }
  226.             }
  227. #endif
  228.             break;
  229.         case SUB:
  230. #if 1
  231.             rd = rs - rt;
  232. #else
  233.             {
  234.             int tmp = rs - rt;
  235.             /* •„†‚ªˆá‚¤ && ‘O‚ÆŒã‚Ì•„†‚ªˆá‚¤@*/
  236.             if ((INT32)(rs^rt)<0 && (INT32)(rs^tmp)<0) {
  237.                 EXCEPTION(E_Ovf);
  238.             } else {
  239.                 rd = tmp;
  240.             }
  241.             }
  242. #endif
  243.             break;
  244.         case ADDU:  rd = rs + rt; break;
  245.         case SUBU:  rd = rs - rt; break;
  246.         case AND:   rd = rs & rt; break;
  247.         case OR:    rd = rs | rt; break;
  248.         case XOR:   rd = rs ^ rt; break;
  249.         case NOR:   rd = ~(rs | rt); break;
  250.  
  251.         case SLT:   rd = ( (INT32)rs < (INT32) rt); break;
  252.         case SLTU:  rd = ((UINT32)rs < (UINT32)rt); break;
  253.  
  254.         case DIV:   if (rt) {
  255.                         rLO = ( INT32)rs/( INT32)rt;
  256.                         rHI=( INT32)rs%( INT32)rt;
  257.                     }
  258.                     break;
  259.         case DIVU:  if (rt) {
  260.                         rLO = (UINT32)rs/(UINT32)rt;
  261.                         rHI=(UINT32)rs%(UINT32)rt;
  262.                     }
  263.                     break;
  264. #ifdef INT64
  265.         case MULT:
  266.             rLO = ((INT64)(INT32)rs*(INT32)rt);
  267.             rHI = ((INT64)(INT32)rs*(INT32)rt)>>32;
  268.             break;
  269.         case MULTU:
  270.             rLO = ((INT64)(UINT32)rs*(UINT32)rt);
  271.             rHI = ((INT64)(UINT32)rs*(UINT32)rt)>>32;
  272.             break;
  273. #else
  274.         case MULT:  mult(rs,rt);  break;
  275.         case MULTU: multu(rs,rt); break;
  276. #endif
  277.  
  278.         case MFHI:  rd = rHI; break;
  279.         case MFLO:  rd = rLO; break;
  280.         case MTHI:  rHI = rs; break;
  281.         case MTLO:  rLO = rs; break;
  282.  
  283.         case JALR:  rd = PC+4; // reg.r[31] = PC+4;
  284.         case JR:    JUMP(rs); SETPC(PC); bioscheck(PC); break;
  285.  
  286.         case BREAK: EXCEPTION(E_Bp); break;
  287.         case SYSCALL:
  288.             PRINTF("syscall: %08x",(int)(reg.r[4]));
  289.             switch(reg.r[4]) {
  290.                 case 0:PRINTF("Exception\n"); break;
  291.                 case 1:PRINTF("EnterCriticalSection\n"); break;
  292.                 case 2:PRINTF("ExitCriticalSection\n"); break;
  293.                 default:PRINTF("%d\n",(int)(reg.r[4]));
  294.             }
  295.             EXCEPTION(E_Sys);
  296.             break;
  297.         default:    NOT_IMPREMENT("special"); break;
  298.         }
  299.         break;
  300.  
  301.     case BCOND:
  302.         switch(rtno){
  303.         case BLTZAL:reg.r[31]=PC+4;
  304.         case BLTZ:  if ((INT32)rs< 0) { JUMP(PC + immS*4); } break;
  305.         case BGEZAL:reg.r[31]=PC+4;
  306.         case BGEZ:  if ((INT32)rs>=0) { JUMP(PC + immS*4); } break;
  307.         default:    NOT_IMPREMENT("bcond"); break;
  308.         }
  309.         break;
  310.  
  311. /* BRANCH/JUMP */
  312.     case JAL:   reg.r[31] = PC+4;
  313.     case J:     JUMP((PC&0xf0000000)|((code&0x03ffffff)<<2)); break;
  314.     case BNE:   if (rt!=rs) { JUMP(PC + immS*4); } break;
  315.     case BEQ:   if (rt==rs) { JUMP(PC + immS*4); } break;
  316.     case BLEZ:  if ((INT32)rs<=0) { JUMP(PC + immS*4); } break;
  317.     case BGTZ:  if ((INT32)rs> 0) { JUMP(PC + immS*4); } break;
  318.  
  319. /* ALU */
  320.     case ADDI:
  321. #if 1
  322.         rt = rs + immS;
  323. #else
  324.         {
  325.         int    tmp = rs + immS;
  326.         /* •„†‚ª“¯‚¶ && ‘O‚ÆŒã‚Ì•„†‚ªˆá‚¤@*/
  327.         if ((INT32)(rs^immS)>=0 && (INT32)(rs^tmp)<0) {
  328.             EXCEPTION(E_Ovf);
  329.         } else {
  330.             rt = tmp;
  331.         }
  332.         }
  333. #endif
  334.         break;
  335.     case ADDIU: rt = rs + immS; break;
  336.     case SLTI:  rt = ( (INT32)rs < immS); break;
  337.     case SLTIU: rt = ((UINT32)rs < (UINT32)immS); break;
  338.     case ANDI:  rt = rs & immU; break;
  339.     case ORI:   rt = rs | immU; break;
  340.     case XORI:  rt = rs ^ immU; break;
  341.     case LUI:   rt = (code<<16); break;
  342.  
  343. /* COP */
  344.     case COP0:
  345.         switch(rsno) {
  346.         case MFC: rt = CPR0[rdno]; /*PRINTF("cop0:r %d\n",rdno);*/ break;
  347.         case CFC: rt = CCR0[rdno]; PRINTF("cop0:\n"); break;
  348.         case MTC: if (rdno!=13 && rdno!=14) CPR0[rdno] = rt; 
  349.                   PRINTF("cop0:w %d,%x\n",(int)rdno,(int)rt);
  350.                     break;
  351.         case CTC: CCR0[rdno] = rt; /*PRINTF("cop0:\n");*/ break;
  352.         case 16:
  353.             if ((code&31)==16) { /* RFE */
  354.                 SR = (SR & ~0xf)| ((SR>>2)&0xf);
  355.                 PRINTF("rfe:%x\n",(int)SR);
  356.                 break;
  357.             }
  358.         default: NOT_IMPREMENT("COP0"); break;
  359.         }
  360.         break;
  361.     case COP2:
  362.         switch(rsno) {
  363.         case MFC: cop2read(rdno   ,CPR2); rt = CPR2[rdno]; break;
  364.         case CFC: cop2read(rdno+32,CPR2); rt = CCR2[rdno]; break;
  365.         case MTC: CPR2[rdno] = rt; cop2write(rdno   ,CPR2); break;
  366.         case CTC: CCR2[rdno] = rt; cop2write(rdno+32,CPR2); break;
  367.         default:
  368.             if (cop2(code&0x1ffffff,CPR2)) 
  369.                 FPSE_Flags |= STOP;
  370.                 break;
  371.         }
  372.         break;
  373.  
  374. /* LOAD/STORE */
  375.     case SB:
  376.         CHECK_WRITEBREAK(adr);
  377.         write8(rs+immS,rt); break;
  378.     case SH: {
  379.         UINT32 adr = rs+immS;
  380.         CHECK_WRITEBREAK(adr);
  381.         if (adr&1) { EXCEPTION(E_DBE); }
  382.               else write16(adr,rt);
  383.         }
  384.         break;
  385.     case SW: {
  386.         UINT32 adr = rs+immS;
  387.         CHECK_WRITEBREAK(adr);
  388.         if (adr&3) { EXCEPTION(E_DBE); }
  389.               else write32(adr,rt);
  390.         }
  391.         break;
  392.     case SWL: {
  393.         UINT32 adr = rs + immS;
  394.         UINT32 data;
  395.         CHECK_WRITEBREAK(adr);
  396.         data = read32(adr&~3);
  397.         switch(adr&3) {
  398.         case 3: data = rt; break;
  399.         case 2: data = (data & 0xff000000) | (rt>> 8); break;
  400.         case 1: data = (data & 0xffff0000) | (rt>>16); break;
  401.         case 0: data = (data & 0xffffff00) | (rt>>24); break;
  402.         }
  403.         write32(adr&~3,data);
  404.         }
  405.         break;
  406.     case SWR: {
  407.         UINT32 adr = rs + immS;
  408.         UINT32 data;
  409.         CHECK_WRITEBREAK(adr);
  410.         data = read32(adr&~3);
  411.         switch(adr&3) {
  412.         case 3: data = (data & 0x00ffffff) | (rt<<24); break;
  413.         case 2: data = (data & 0x0000ffff) | (rt<<16); break;
  414.         case 1: data = (data & 0x000000ff) | (rt<< 8); break;
  415.         case 0: data = rt; break;
  416.         }
  417.         write32(adr&~3,data);
  418.         }
  419.         break;
  420.  
  421.     case LB:
  422.         CHECK_READBREAK(rs+immS);
  423.         rt = (INT8)read8(rs+immS); break;
  424.     case LBU:
  425.         CHECK_READBREAK(rs+immS);
  426.         rt = read8(rs+immS); break;
  427.     case LH: {
  428.         UINT32 adr = rs + immS;
  429.         CHECK_READBREAK(rs+immS);
  430.         if (adr&1) { EXCEPTION(E_DBE); }
  431.               else { UINT32 tmp = (INT16)read16(adr); if (rtno) rt=tmp; }
  432.         }
  433.         break;
  434.     case LHU: {
  435.         UINT32 adr = rs + immS;
  436.         CHECK_READBREAK(adr);
  437.         if (adr&1) { EXCEPTION(E_DBE); }
  438.               else { UINT32 tmp = read16(adr); if (rtno) rt=tmp; }
  439.         }
  440.         break;
  441.     case LW: {
  442.         UINT32 adr = rs + immS;
  443.         CHECK_READBREAK(adr);
  444.         if (adr&3) { EXCEPTION(E_DBE); }
  445.         else { UINT32 tmp = read32(adr); if (rtno) rt=tmp; }
  446.         }
  447.         break;
  448.     case LWL: {
  449.         UINT32 adr = rs + immS;
  450.         UINT32 data;
  451.         CHECK_READBREAK(adr);
  452.         data = read32(adr&~3);
  453.         switch(adr&3) {
  454.         case 3: rt = data; break;
  455.         case 2: rt = (rt & 0x000000ff) | (data<< 8); break;
  456.         case 1: rt = (rt & 0x0000ffff) | (data<<16); break;
  457.         case 0: rt = (rt & 0x00ffffff) | (data<<24); break;
  458.         }
  459.         }
  460.         break;
  461.     case LWR: {
  462.         UINT32 adr = rs + immS;
  463.         UINT32 data;
  464.         CHECK_READBREAK(adr);
  465.         data = read32(adr&~3);
  466.         switch(adr&3) {
  467.         case 3: rt = (rt & 0xffffff00) | (data>>24); break;
  468.         case 2: rt = (rt & 0xffff0000) | (data>>16); break;
  469.         case 1: rt = (rt & 0xff000000) | (data>> 8); break;
  470.         case 0: rt = data; break;
  471.         }
  472.         }
  473.         break;
  474.  
  475.     case SWC0: {
  476.         UINT32 adr = rs+immS;
  477.         CHECK_WRITEBREAK(adr);
  478.         if (adr&3) { EXCEPTION(E_DBE); }
  479.         else write32(adr,CPR0[rtno]);
  480.         }
  481.         break;
  482.     case LWC0: {
  483.         UINT32 adr = rs+immS;
  484.         CHECK_READBREAK(adr);
  485.         if (adr&3) { EXCEPTION(E_DBE); }
  486.               else CPR0[rtno] = read32(rs+immS);
  487.         }
  488.         break;
  489.     case SWC2: {
  490.         UINT32 adr = rs+immS;
  491.         CHECK_WRITEBREAK(adr);
  492.         if (adr&3) { EXCEPTION(E_DBE); }
  493.               else { cop2read(rtno,CPR2); write32(adr,CPR2[rtno]); }
  494.         }
  495.         break;
  496.     case LWC2: {
  497.         UINT32 adr = rs+immS;
  498.         CHECK_READBREAK(adr);
  499.         if (adr&3) { EXCEPTION(E_DBE); }
  500.               else { CPR2[rtno] = read32(adr); cop2write(rtno,CPR2); }
  501.         }
  502.         break;
  503.     default: NOT_IMPREMENT("??"); break;
  504.     }
  505.     reg.r[0] = 0;
  506. }